﻿namespace GeoCode.Core
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks></remarks>
    public struct Box
    {
        /// <summary>
        /// 
        /// </summary>
        public static readonly Box Empty;
        /// <summary>
        /// 
        /// </summary>
        private readonly double _east;

        /// <summary>
        /// 
        /// </summary>
        private readonly double _north;
        /// <summary>
        /// 
        /// </summary>
        private readonly double _south;
        /// <summary>
        /// 
        /// </summary>
        private readonly double _west;

        /// <summary>
        /// Initializes a new instance of the <see cref="Box"/> struct.
        /// </summary>
        /// <param name="north">The north.</param>
        /// <param name="south">The south.</param>
        /// <param name="east">The east.</param>
        /// <param name="west">The west.</param>
        /// <remarks></remarks>
        public Box(double north, double south, double east, double west)
        {
            this._north = north;
            this._south = south;
            this._east = east;
            this._west = west;
        }

        /// <summary>
        /// Gets the north.
        /// </summary>
        /// <remarks></remarks>
        public double North
        {
            get { return _north; }
        }

        /// <summary>
        /// Gets the south.
        /// </summary>
        /// <remarks></remarks>
        public double South
        {
            get { return _south; }
        }

        /// <summary>
        /// Gets the east.
        /// </summary>
        /// <remarks></remarks>
        public double East
        {
            get { return _east; }
        }

        /// <summary>
        /// Gets the west.
        /// </summary>
        /// <remarks></remarks>
        public double West
        {
            get { return _west; }
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
        /// <remarks></remarks>
        public override int GetHashCode()
        {
            return _north.GetHashCode() ^ _south.GetHashCode() ^ _east.GetHashCode() ^ _west.GetHashCode();
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">Another object to compare to.</param>
        /// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
        /// <remarks></remarks>
        public override bool Equals(object obj)
        {
            if (!(obj is Box))
                return false;

            return Equals((Box)obj);
        }

        /// <summary>
        /// Equalses the specified other.
        /// </summary>
        /// <param name="other">The other.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public bool Equals(Box other)
        {
            if (_north != other.North)return false;
            if (_south != other.South)return false;
            if (_east != other.East)return false;
            if (_west != other.West)return false;
            return true;
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="box1">The box1.</param>
        /// <param name="box2">The box2.</param>
        /// <returns>The result of the operator.</returns>
        /// <remarks></remarks>
        public static bool operator ==(Box box1, Box box2)
        {
            return box1.Equals(box2);
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="box1">The box1.</param>
        /// <param name="box2">The box2.</param>
        /// <returns>The result of the operator.</returns>
        /// <remarks></remarks>
        public static bool operator !=(Box box1, Box box2)
        {
            return !box1.Equals(box2);
        }
    }
}